// relay.c
#include <nvs_flash.h>
#include "relay.h"
#include "esp_log.h"
#include "utils/i2c/i2c_master/i2c_master_utils.h"
#include "system_init/system_init.h"
static const char* TAG = "RELAY";
static const char* NVS_NAMESPACE = "relay_config";
static const char* ADDR_KEY = "relay_addr";
static uint8_t default_relay_addr = 0x20; // 默认I2C地址
// 定义 I2C 总线编号
#define I2C_MASTER_PORT_NUM I2C_NUM_0
static uint8_t cached_keypad_addr = 0;    // 缓存的键盘模块地址
static bool addr_cached = false;          // 地址是否已缓存的标志

uint8_t config_get_relay_addr(void) {
    if (addr_cached) {
        return cached_keypad_addr;
    }
    nvs_handle_t my_handle;
    uint8_t addr;
    esp_err_t err;

    // 打开
    err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &my_handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err));
        addr = default_relay_addr;
    }else{

        // 读取保存的地址
        err = nvs_get_u8(my_handle, ADDR_KEY, &addr);
        nvs_close(my_handle);

        switch (err) {
            case ESP_OK:
                ESP_LOGI(TAG, "Relay address loaded from NVS: 0x%02X", addr);
                break;
            case ESP_ERR_NVS_NOT_FOUND:
                addr = default_relay_addr;
                ESP_LOGW(TAG, "Relay address not found in NVS, using default: 0x%02X", default_relay_addr);
                break;
            default :
                addr = default_relay_addr;
                ESP_LOGE(TAG, "Error (%s) reading relay address from NVS!", esp_err_to_name(err));
                break;
        }
    }
    // 缓存地址
    cached_keypad_addr = addr;
    addr_cached = true;

    return addr;
}

esp_err_t config_set_relay_addr(uint8_t addr) {
    nvs_handle_t my_handle;
    esp_err_t err;

    // 打开
    err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &my_handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Error (%s) opening NVS handle for writing!", esp_err_to_name(err));
        return err;
    }

    // 保存地址
    err = nvs_set_u8(my_handle, ADDR_KEY, addr);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Error (%s) setting relay address in NVS!", esp_err_to_name(err));
    } else {
        // 提交
        err = nvs_commit(my_handle);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "Error (%s) committing relay address to NVS!", esp_err_to_name(err));
        } else {
            // 更新缓存的地址
            cached_keypad_addr = addr;
            addr_cached = true;
            ESP_LOGI(TAG, "Relay address saved to NVS: 0x%02X", addr);
        }
    }

    // 关闭
    nvs_close(my_handle);
    return err;
}
// 写入PCF8574模块数据
static esp_err_t write_pcf8574(uint8_t data) {
    uint8_t addr = config_get_relay_addr(); // 从配置获取地址
    esp_err_t err;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE, true);
    i2c_master_write_byte(cmd, data, true);
    i2c_master_stop(cmd);
    ESP_LOGD("I2C", "Writing data 0x%02X to address 0x%02X", data, addr);
    err = i2c_master_cmd_begin(I2C_MASTER_PORT_NUM, cmd, pdMS_TO_TICKS(2000));
    if (err != ESP_OK) {
        ESP_LOGE("I2C", "I2C write failed with error code %d", err);
    }
    i2c_cmd_link_delete(cmd);
    return err;
}

// 存储继电器状态，0 表示关，1 表示开
uint8_t relay_states[8] = {0};

//切换指定idx继电器状态 取反
void switcRelayState(uint8_t idx) {
    uint8_t state = !relay_states[idx];
    setRelayState(idx, state);
}

//设置指定idx继电器状态
void setRelayState(uint8_t idx, uint8_t state) {
    relay_states[idx] = state;
    uint8_t data = 0;
    for (int i = 0; i < 8; i++) {
        data |= (relay_states[i] << i);
    }
    esp_err_t err = write_pcf8574(data);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to write relay state: %d", err);
    }
}

// 设置新的继电器模块地址并保存
esp_err_t relay_set_module_addr(uint8_t addr) {
    return config_set_relay_addr(addr);
}

void relay_handle_keypad_event(keypad_event_t event) {
    if (event.state == 1) {  // 按键按下 取反
        switcRelayState(event.pin);
    }
}

int relay_init(void) {
    // 初始化系统（包括NVS）
    esp_err_t err = system_init();
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "System initialization failed for relay");
        return err;
    }

    // 初始化I2C
    err = i2c_master_init();
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "I2C initialization failed for relay");
        return err;
    }
    return ESP_OK;
    // 加载并应用保存的继电器状态（可选功能扩展）
    // 这里可以添加加载继电器状态的代码
}